//重新数组里的方法并新增自己的逻辑

import {
  observe
} from "./index";

//操作原数组的方法push/shift/unshift/pop/slice/splice/sort/reverse
//filter不会操作原数组，不用进行改写
let oldArrayProtoMethods = Array.prototype;

//单独定义一个对象存放着新修改后的数组原型方法
//根据已经有的对象原型新建一个新的对象
export let newArrayProtoMethods = Object.create(oldArrayProtoMethods);

let methods = ['push', 'shift', 'unshift', 'pop', 'slice', 'splice', 'sort', 'reverse'];

//观察数组里的每一项元素,增加响应式处理
export function observeArray(insertedElement) {
  for (let i = 0; i < insertedElement.length; i++) {
    observe(insertedElement[i]);
  }
}


//对嵌套数组也实现数组依赖收集
export function dependArray(value) {
  // console.log(value);
  //[1, 4, 6, [8], {} ,10, __ob__: (...)]

  for (let i = 0; i < value.length; i++) {
    let currentItem = value[i];
    // console.log(currentItem);
    //1 4 6 [8] {} 10

    //证明该项是数组/对象
    if (currentItem.__ob__) {
      //通过__ob__里面的dep实例里的depend方法进行依赖收集
      currentItem.__ob__.dep.depend();

      //出现数组再次嵌套时递归收集依赖
      if (Array.isArray(currentItem)) {
        dependArray(currentItem);
      }
    }
  }

}


//给data底下的数组属性新增一个原型，原型上有method这些原数组方法
methods.forEach(method => {
  newArrayProtoMethods[method] = function (...args) {
    // console.log('This is code edit area in arrayHandle methods');
    // console.log(args);
    //开发者写vm.nums.push(10)时：args相当于写入的参数

    //保留原数组的操作的方法逻辑
    //可以改写数组方法
    //传入this，让指向调用者
    let result = oldArrayProtoMethods[method].apply(this, args);

    let insertedElement;

    switch (method) {
      case 'push':
      case 'unshift':
        insertedElement = args;
        break;
      case 'splice':
        //[].splice(start,删除几个元素,新增元素)
        //可以拿到数组最后一项
        insertedElement = args.slice(2);
      default:
        break;
    }

    if (insertedElement) {
      observeArray(insertedElement);
    }


    //这里的区域可以写新增的自定义逻辑区域

    //访问当前数组的实例
    //xxx.push
    //this指向调用者 即 数组

    /**
     * console.log(this);
     * [
     *   0: 1,
     *   1: 4,
     *   2: 6,
     *   3: 10,
     *   length: 4,
     *   __ob__: Observer,
     *   get __ob__: () => this
     * ]
     */

    // console.log(this.__ob__);
    //Observer {dep: Dep}

    //访问dep.notify()去发布遍历每一个watcher并执行底下的update方法进行页面更新
    this.__ob__.dep.notify();


    return result;
  }
})